package com.fyakm.daodejing.stock.service;


import java.math.BigDecimal;
import java.util.List;
import com.fyakm.daodejing.stock.domain.StockHistoryItem;

/**
 * 回测类，用于评估不同股票交易策略的有效性
 */
public class Backtester {
    private StockTradingStrategy strategy;
    private BigDecimal initialCapital;

    /**
     * 构造函数，初始化回测所需的策略和初始资金
     * @param strategy 股票交易策略
     * @param initialCapital 初始资金
     */
    public Backtester(StockTradingStrategy strategy, BigDecimal initialCapital) {
        this.strategy = strategy;
        this.initialCapital = initialCapital;
    }

    /**
     * 执行回测过程
     * @param historyItems 股票历史数据列表
     * @return 回测结束后的最终资金
     */
    public BigDecimal backtest(List<StockHistoryItem> historyItems) {
        BigDecimal capital = initialCapital;
        BigDecimal shares = BigDecimal.ZERO;

        for (int i = 0; i < historyItems.size(); i++) {
            List<StockHistoryItem> currentHistory = historyItems.subList(0, i + 1);
            BigDecimal tradingQuantity = strategy.executeStrategy(currentHistory);

            if (tradingQuantity.compareTo(BigDecimal.ZERO) > 0) {
                // 买入操作
                BigDecimal buyCost = tradingQuantity.multiply(historyItems.get(i).getClose());
                if (capital.compareTo(buyCost) >= 0) {
                    capital = capital.subtract(buyCost);
                    shares = shares.add(tradingQuantity);
                }
            } else if (tradingQuantity.compareTo(BigDecimal.ZERO) < 0) {
                // 卖出操作
                BigDecimal sellQuantity = tradingQuantity.abs();
                if (shares.compareTo(sellQuantity) >= 0) {
                    BigDecimal sellIncome = sellQuantity.multiply(historyItems.get(i).getClose());
                    capital = capital.add(sellIncome);
                    shares = shares.subtract(sellQuantity);
                }
            }
        }

        // 计算剩余股票的价值并加入最终资金
        capital = capital.add(shares.multiply(historyItems.get(historyItems.size() - 1).getClose()));
        return capital;
    }
}